﻿
#Copyright (C) 2011 Daniele Simonetti
#
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#

### PySide ###
from PySide import QtCore, QtGui

### STAR RATING ###

class StarRating:
    Editable = 1
    ReadOnly = 2
    
    PaintingScaleFactor = 24
    
    def __init__(self, star_count = 1, max_star_count = 5):
        self.star_count = star_count
        self.max_star_count = max_star_count
        
        self.star_full = QtGui.QIcon(':/icons/star-full.png')
        self.star_half = QtGui.QIcon(':/icons/star-half.png')
        self.star_empty = QtGui.QIcon(':/icons/star-empty.png')        
        
    def paint(self, painter, rect, palette, mode):
        painter.save()
                
        painter.setRenderHint(QtGui.QPainter.Antialiasing, True)
        painter.setPen(QtCore.Qt.NoPen);        
        
        yOffset = (rect.height() - StarRating.PaintingScaleFactor) / 2
        
        painter.translate(-self.sizeHint().width()/2+20, 0)
        #painter.scale(StarRating.PaintingScaleFactor, StarRating.PaintingScaleFactor)
        
        
        for i in range(0, self.max_star_count):
            if i < self.star_count:
                self.star_full.paint(painter, rect)
            else:
                self.star_empty.paint(painter, rect)
            painter.translate(StarRating.PaintingScaleFactor, 0.0);
                
        painter.restore()
        
    def sizeHint(self):
        return QtCore.QSize(24*self.max_star_count+20,1)
        
## STAR EDITOR ##        
class StarEditor(QtGui.QWidget):
    #define signals
    editingFinished = QtCore.Signal()
    
    def __init__(self, parent=None):
        super(StarEditor, self).__init__(parent)
        self.star_rating = None
        self.setMouseTracking(True)
        self.setAutoFillBackground(True)
    
    def sizeHint(self):
        return self.star_rating.sizeHint()
        
    def paintEvent(self, ev):
        painter = QtGui.QPainter(self)
        self.star_rating.paint(painter, self.rect(), self.palette(), StarRating.Editable)
        
    def mouseMoveEvent(self, ev):
     star = self.starAtPosition(ev.x())
     if star != self.star_rating.star_count and star != -1:
        self.star_rating.star_count = star
        self.update()
        
    def mouseReleaseEvent(self, ev):
        self.editingFinished.emit()
        
    def starAtPosition(self, x):
     star = (x / (self.star_rating.sizeHint().width() / self.star_rating.max_star_count)) + 1
     if star <= 0  or star > self.star_rating.max_star_count:
        return -1
     return star
     

## STAR ITEM DELEGATE ##     
class StarDelegate(QtGui.QStyledItemDelegate):    
    def __init__(self, parent=None):
        super(StarDelegate, self).__init__(parent)
        pass
        
    def paint(self, painter, option, index):
        if not index.isValid():
            super(StarDelegate, self).paint(painter, option, index)
            return
            
        rating_value = index.data() or 0
        br_bg = index.data(QtCore.Qt.BackgroundRole)
        star_rating = StarRating(int(rating_value))
        
        if (option.state & QtGui.QStyle.State_Selected) == QtGui.QStyle.State_Selected:
            painter.fillRect(option.rect, option.palette.highlight())       
        elif br_bg is not None:
            painter.fillRect(option.rect, br_bg)
        
        star_rating.paint(painter, option.rect, option.palette, StarRating.ReadOnly) 
    
    def sizeHint(self, option, index):
        if not index.isValid():
            super(StarDelegate, self).paint(painter, option, index)
            return
        rating_value = index.data() or 0
        star_rating = StarRating(int(rating_value))
        
        return star_rating.sizeHint()
        
    def createEditor(self, parent, option, index):
        if not index.isValid():
            super(StarDelegate, self).paint(painter, option, index)
            return
        editor = StarEditor(parent)
        editor.editingFinished.connect(self.commitAndCloseEditor)
        return editor
        
    def setEditorData(self, editor, index):
        if not index.isValid():
            super(StarDelegate, self).paint(painter, option, index)
            return
        rating_value = index.data() or 0
        editor.star_rating = StarRating(int(rating_value))
        
        
    def setModelData(self, editor, model, index):
        if not index.isValid():
            super(StarDelegate, self).paint(painter, option, index)
            return
        model.items[index.row()]['rating'] = editor.star_rating.star_count
        item = model.items[index.row()] 
        model.updateStatus(item['showid'])        
        
    def commitAndCloseEditor(self):
        editor = self.sender()
        self.commitData.emit(editor)
        self.closeEditor.emit(editor)
        
